<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>信用评分与违约预测平台</title>
    <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-QWTKZyjpPEjISv5WaRU9OFeRpok6YctnYmDr5pNlyT2bRjXh0JMhjY6hW+ALEwIH" crossorigin="anonymous">
    <style>
        body {
            background-color: #f8f9fa;
            overflow-x: hidden;
            margin: 0; /* 消除默认边距 */
        }
        .container {
            max-width: 1200px;
        }
        .card {
            border: none;
            box-shadow: 0 4px 8px rgba(0,0,0,0.05);
            transition: all 0.3s ease-in-out;
        }
        .card:hover {
            box-shadow: 0 8px 16px rgba(0,0,0,0.1);
        }
        .btn-primary {
            background-color: #0d6efd;
            border-color: #0d6efd;
        }
        #results-card .display-4 {
            color: #0d6efd;
            font-weight: 500;
        }
        .form-text {
            font-size: 0.8rem;
        }

        /* 登录页面布局 - 左右自然分布，无分割线 */
        .auth-container {
            display: flex;
            min-height: 100vh;
            background: linear-gradient(90deg, #0f172a, #1e293b); /* 深色调蓝灰渐变，更贴合参考图 */
        }
        
        /* 左侧动画区域 - 居中展示标题，粒子呈星云效果 */
        .animation-side {
            flex: 1;
            position: relative;
            overflow: hidden;
            display: flex;
            align-items: center;
            justify-content: center;
        }
        
        .animation-overlay {
            position: relative;
            z-index: 10;
            text-align: left;
            padding: 2rem;
        }
        
        .animation-title {
            font-size: 2rem;
            font-weight: 700;
            color: #ffffff;
            text-shadow: 0 2px 4px rgba(0, 0, 0, 0.5);
            margin-bottom: 1rem;
        }
        
        /* 右侧登录区域 - 表单更紧凑，背景融合 */
        .auth-side {
            flex: 1;
            display: flex;
            align-items: center;
            justify-content: center;
            padding: 2rem;
        }
        
        .auth-card {
            width: 100%;
            max-width: 350px;
            background-color: rgba(255, 255, 255, 0.05);
            border-radius: 8px;
            backdrop-filter: blur(8px);
            color: white;
            box-shadow: none; /* 去除阴影，增强背景融合感 */
            padding: 1.5rem;
        }
        
        .auth-card .form-control {
            background-color: rgba(255, 255, 255, 0.1);
            border: 1px solid rgba(255, 255, 255, 0.2);
            color: white;
        }
        
        .auth-card .form-control:focus {
            background-color: rgba(255, 255, 255, 0.15);
            border-color: #0d6efd;
            color: white;
        }
        
        .auth-card .nav-link {
            color: rgba(255, 255, 255, 0.7);
        }
        
        .auth-card .nav-link.active {
            background-color: rgba(13, 110, 253, 0.8);
            color: white;
        }
        
        .auth-card .btn-outline-primary {
            color: #0d6efd;
            border-color: #0d6efd;
        }
        
        .auth-card .btn-outline-primary:hover {
            background-color: #0d6efd;
            color: white;
        }
        
        .form-label.small {
            font-size: 0.9rem; /* 缩小标签字体，更紧凑 */
        }

        /* 动画元素 - 星云风格粒子 */
        .particle {
            position: absolute;
            border-radius: 50%;
            background-color: rgba(13, 110, 253, 0.8);
            box-shadow: 0 0 8px rgba(13, 110, 253, 0.6);
            pointer-events: none;
            transition: all 0.2s ease;
        }
        
        .data-line {
            position: absolute;
            background-color: rgba(13, 110, 253, 0.3);
            transform-origin: 0 0;
            pointer-events: none;
            height: 1px; /* 更细的线条 */
        }

        /* 破碎转场效果 */
        .shatter-effect {
            position: fixed;
            top: 0;
            left: 0;
            width: 100%;
            height: 100%;
            pointer-events: none;
            z-index: 1000;
            display: none;
        }
        
        .shatter-piece {
            position: absolute;
            background-color: inherit;
            transition: all 0.6s cubic-bezier(0.25, 0.46, 0.45, 0.94);
        }

        /* 预测页面样式 */
        #prediction-section {
            opacity: 0;
            transition: opacity 0.5s ease-in-out 0.3s;
        }
        
        #prediction-section.visible {
            opacity: 1;
        }

        @media (max-width: 768px) {
            .auth-container {
                flex-direction: column;
            }
            
            .animation-side {
                height: 300px;
            }
            
            .animation-title {
                font-size: 1.5rem;
            }
        }
    </style>
</head>
<body>
    <!-- 破碎效果容器 -->
    <div class="shatter-effect" id="shatter-effect"></div>

    <!-- 认证部分 -->
    <div class="auth-container" id="auth-container">
        <!-- 左侧动画区域 -->
        <div class="animation-side" id="animation-side">
            <div class="animation-overlay">
                <h2 class="animation-title">智能信用评分系统</h2>
                <p class="animation-subtitle" style="color: rgba(255,255,255,0.8);">基于机器学习算法的信用风险预测，精准评估违约概率</p>
            </div>
        </div>
        
        <!-- 右侧登录区域 -->
        <div class="auth-side">
            <div class="auth-card">
                <div class="card-body p-3">
                    <h4 class="text-center mb-3">欢迎使用信用评分平台</h4>
                    <ul class="nav nav-pills nav-fill mb-2" id="pills-tab" role="tablist">
                        <li class="nav-item" role="presentation">
                            <button class="nav-link active" id="pills-login-tab" data-bs-toggle="pill" data-bs-target="#pills-login" type="button" role="tab" aria-controls="pills-login" aria-selected="true">登录</button>
                        </li>
                        <li class="nav-item" role="presentation">
                            <button class="nav-link" id="pills-register-tab" data-bs-toggle="pill" data-bs-target="#pills-register" type="button" role="tab" aria-controls="pills-register" aria-selected="false">注册</button>
                        </li>
                    </ul>
                    <div class="tab-content" id="pills-tabContent">
                        <!-- 登录表单 -->
                        <div class="tab-pane fade show active" id="pills-login" role="tabpanel" aria-labelledby="pills-login-tab">
                            <form id="login-form">
                                <div class="mb-2">
                                    <label for="login-username" class="form-label small">用户名</label>
                                    <input type="text" class="form-control" id="login-username" required>
                                </div>
                                <div class="mb-3">
                                    <label for="login-password" class="form-label small">密码</label>
                                    <input type="password" class="form-control" id="login-password" required>
                                </div>
                                <div class="d-grid">
                                    <button type="submit" class="btn btn-primary">登录</button>
                                </div>
                            </form>
                        </div>
                        <!-- 注册表单 -->
                        <div class="tab-pane fade" id="pills-register" role="tabpanel" aria-labelledby="pills-register-tab">
                            <form id="register-form">
                                <div class="mb-2">
                                    <label for="register-username" class="form-label small">用户名</label>
                                    <input type="text" class="form-control" id="register-username" required>
                                </div>
                                <div class="mb-3">
                                    <label for="register-password" class="form-label small">密码</label>
                                    <input type="password" class="form-control" id="register-password" required>
                                </div>
                                <div class="d-grid">
                                    <button type="submit" class="btn btn-outline-primary">注册</button>
                                </div>
                            </form>
                        </div>
                    </div>
                </div>
            </div>
        </div>
    </div>

    <!-- 预测部分 -->
    <div id="prediction-section" class="container mt-4 mb-4">
        <div class="d-flex justify-content-between align-items-center mb-4">
            <h2 class="mb-0">信用风险评估模型</h2>
            <button id="logout-btn" class="btn btn-sm btn-outline-danger">登出</button>
        </div>
        
        <div id="prediction-message" class="mb-3"></div>

        <div class="row g-4">
            <!-- 预测表单列 -->
            <div class="col-lg-7">
                <div class="card h-100">
                    <div class="card-body p-4">
                        <h5 class="card-title mb-4">请输入客户特征信息</h5>
                        <form id="prediction-form" class="row g-3">
                            <div class="col-md-6">
                                <label for="x_153" class="form-label">最近6个月信用卡总额度</label>
                                <input type="number" class="form-control" id="x_153" name="x_153" required step="any" placeholder="例如: 50000">
                                <div class="form-text">反映用户的短期授信水平。</div>
                            </div>
                            <div class="col-md-6">
                                <label for="x_251" class="form-label">最近1年身份证+手机号多平台申请次数</label>
                                <input type="number" class="form-control" id="x_251" name="x_251" required step="any" placeholder="例如: 10">
                                <div class="form-text">高频申请可能预示着短期资金紧张。</div>
                            </div>
                            <div class="col-md-6">
                                <label for="x_201" class="form-label">历史最大的逾期期数</label>
                                <input type="number" class="form-control" id="x_201" name="x_201" required step="any" placeholder="例如: 2">
                                <div class="form-text">衡量用户历史上最严重的信用违约事件。</div>
                            </div>
                            <div class="col-md-6">
                                <label for="x_200" class="form-label">历史逾期总次数</label>
                                <input type="number" class="form-control" id="x_200" name="x_200" required step="any" placeholder="例如: 3">
                                <div class="form-text">反映用户的还款习惯和信用稳定性。</div>
                            </div>
                            <div class="col-md-6">
                                <label for="x_220" class="form-label">最近1年主动查询的机构数</label>
                                <input type="number" class="form-control" id="x_220" name="x_220" required step="any" placeholder="例如: 5">
                                <div class="form-text">用户主动发起的信贷查询行为，是信贷需求的直接体现。</div>
                            </div>
                            <div class="col-md-6">
                                <label for="x_232" class="form-label">最近6个月身份证多平台申请次数</label>
                                <input type="number" class="form-control" id="x_232" name="x_232" required step="any" placeholder="例如: 8">
                                <div class="form-text">短期内的多头借贷申请行为是重要的风险信号。</div>
                            </div>
                            <div class="col-md-6">
                                <label for="x_243" class="form-label">最近1年在非银机构的申请次数</label>
                                <input type="number" class="form-control" id="x_243" name="x_243" required step="any" placeholder="例如: 4">
                                <div class="form-text">在非银行金融机构的借贷行为可能意味着更高的风险偏好。</div>
                            </div>
                            <div class="col-md-6">
                                <label for="x_147" class="form-label">信用卡已用额度</label>
                                <input type="number" class="form-control" id="x_147" name="x_147" required step="any" placeholder="例如: 25000">
                                <div class="form-text">衡量用户当前的负债水平和资金压力。</div>
                            </div>
                            <div class="col-md-6">
                                <label for="x_155" class="form-label">信用卡额度使用率</label>
                                <input type="number" class="form-control" id="x_155" name="x_155" required step="any" placeholder="例如: 0.5">
                                <div class="form-text">高使用率可能表示用户依赖信用卡周转，财务状况紧张。</div>
                            </div>
                            <div class="col-md-6">
                                <label for="x_151" class="form-label">信用卡最大额度</label>
                                <input type="number" class="form-control" id="x_151" name="x_151" required step="any" placeholder="例如: 100000">
                                <div class="form-text">代表金融机构对用户信用的最高认可度。</div>
                            </div>
                            <div class="col-md-6">
                                <label for="x_143" class="form-label">最近12个月贷后管理查询机构数</label>
                                <input type="number" class="form-control" id="x_143" name="x_143" required step="any" placeholder="例如: 6">
                                <div class="form-text">贷后查询频率可反映用户现有债务的风险状况。</div>
                            </div>
                            <div class="col-12 mt-4">
                                <div class="d-grid">
                                     <button type="submit" class="btn btn-primary btn-lg">提交预测</button>
                                </div>
                            </div>
                        </form>
                    </div>
                </div>
            </div>
            <!-- 结果列 -->
            <div class="col-lg-5">
                <div id="results-card" class="card h-100">
                    <div class="card-body p-4 text-center d-flex flex-column justify-content-center">
                        <h5 class="card-title mb-3">预测结果</h5>
                        <div id="results-area">
                            <p class="text-muted">请填写左侧表单并提交以获取预测结果。</p>
                        </div>
                    </div>
                </div>
            </div>
        </div>
    </div>

    <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/js/bootstrap.bundle.min.js" integrity="sha384-YvpcrYf0tY3lHB60NNkmXc5s9fDVZLESaAA55NDzOxhy9GkcIdslK1eN7N6jIeHz" crossorigin="anonymous"></script>

    <script>
        document.addEventListener('DOMContentLoaded', () => {
            // DOM元素
            const authContainer = document.getElementById('auth-container');
            const predictionSection = document.getElementById('prediction-section');
            const animationSide = document.getElementById('animation-side');
            const shatterEffect = document.getElementById('shatter-effect');
            
            const registerForm = document.getElementById('register-form');
            const loginForm = document.getElementById('login-form');
            const predictionForm = document.getElementById('prediction-form');
            
            const logoutBtn = document.getElementById('logout-btn');
            
            const authMessage = document.getElementById('auth-message');
            const predictionMessage = document.getElementById('prediction-message');
            const resultsArea = document.getElementById('results-area');

            const API_BASE_URL = 'http://127.0.0.1:5000';

            // 创建星云风格机器学习动画
            createNebulaAnimation();

            // 视图更新函数
            const updateView = () => {
                const token = localStorage.getItem('jwtToken');
                if (token) {
                    authContainer.style.display = 'none';
                    predictionSection.classList.add('visible');
                } else {
                    authContainer.style.display = 'flex';
                    predictionSection.classList.remove('visible');
                }
            };
            
            // 显示认证消息
            const showAuthMessage = (message, isError = false) => {
                authMessage.textContent = message;
                authMessage.className = isError ? 'alert alert-danger' : 'alert alert-success';
            };

            // 显示预测消息
            const showPredictionMessage = (message, isError = true) => {
                predictionMessage.innerHTML = `<div class="alert ${isError ? 'alert-danger' : 'alert-success'}">${message}</div>`;
            };

            // 注册处理
            registerForm.addEventListener('submit', async (e) => {
                e.preventDefault();
                const username = document.getElementById('register-username').value;
                const password = document.getElementById('register-password').value;

                try {
                    const response = await fetch(`${API_BASE_URL}/register`, {
                        method: 'POST',
                        headers: { 'Content-Type': 'application/json' },
                        body: JSON.stringify({ username, password })
                    });
                    
                    const data = await response.json();
                    if (response.ok) {
                        showAuthMessage(data.message);
                        registerForm.reset();
                    } else {
                        showAuthMessage(data.message, true);
                    }
                } catch (error) {
                    showAuthMessage('网络错误，请稍后重试。', true);
                }
            });

            // 登录处理
            loginForm.addEventListener('submit', async (e) => {
                e.preventDefault();
                const username = document.getElementById('login-username').value;
                const password = document.getElementById('login-password').value;
                
                try {
                    const response = await fetch(`${API_BASE_URL}/login`, {
                        method: 'POST',
                        headers: {
                            'Authorization': 'Basic ' + btoa(`${username}:${password}`)
                        }
                    });

                    const data = await response.json();
                    if (response.ok) {
                        localStorage.setItem('jwtToken', data.token);
                        authMessage.innerHTML = '';
                        
                        // 触发破碎动画然后更新视图
                        triggerShatterEffect(() => {
                            updateView();
                        });
                    } else {
                        showAuthMessage(data.message, true);
                    }
                } catch (error) {
                     showAuthMessage('网络错误，请稍后重试。', true);
                }
            });

            // 登出处理
            logoutBtn.addEventListener('click', () => {
                localStorage.removeItem('jwtToken');
                resultsArea.innerHTML = '<p class="text-muted">请填写左侧表单并提交以获取预测结果。</p>';
                predictionMessage.innerHTML = '';
                predictionForm.reset();
                updateView();
            });

            // 预测处理
            predictionForm.addEventListener('submit', async (e) => {
                e.preventDefault();
                const token = localStorage.getItem('jwtToken');
                if (!token) {
                    showPredictionMessage('认证失败，请重新登录。');
                    updateView();
                    return;
                }

                const formData = new FormData(predictionForm);
                const payload = {};
                for (let [key, value] of formData.entries()) {
                    payload[key] = parseFloat(value);
                }

                try {
                    const response = await fetch(`${API_BASE_URL}/predict`, {
                        method: 'POST',
                        headers: {
                            'Content-Type': 'application/json',
                            'x-access-token': token 
                        },
                        body: JSON.stringify(payload)
                    });

                    const data = await response.json();
                    predictionMessage.innerHTML = '';

                    if (response.ok) {
                        const score = data.credit_score;
                        const prob = data.default_probability;
                        const predictionText = prob > 0.5 ? '是' : '否';
                        const predictionClass = prob > 0.5 ? 'text-danger' : 'text-success';
                        
                        resultsArea.innerHTML = `
                            <div>
                                <h6 class="text-muted">信用得分</h6>
                                <p class="display-4">${score}</p>
                            </div>
                            <div class="mt-3">
                                <h6 class="text-muted">预测是否违约</h6>
                                <p class="h3 ${predictionClass}">${predictionText}</p>
                                <small class="text-muted">(违约概率: ${(prob * 100).toFixed(2)}%)</small>
                            </div>
                        `;
                    } else {
                        if (response.status === 401) {
                            showPredictionMessage(`认证无效: ${data.message} 即将返回登录页面...`, true);
                            setTimeout(() => {
                                logoutBtn.click();
                            }, 3000);
                        } else {
                            showPredictionMessage(`预测失败: ${data.error || data.message}`, true);
                        }
                        resultsArea.innerHTML = '<p class="text-muted">预测出错，请检查输入或联系管理员。</p>';
                    }
                } catch (error) {
                    showPredictionMessage('网络请求失败，请检查您的网络连接或联系管理员。', true);
                }
            });

            // 创建星云风格机器学习动画
            function createNebulaAnimation() {
                const particlesCount = 50; // 更多粒子，营造星云感
                const linesCount = 10;     // 减少线条，突出粒子
                let particles = [];
                let lines = [];
                let mouse = { x: null, y: null, radius: 180 };

                // 创建粒子（分布更偏向左侧，模拟星云）
                for (let i = 0; i < particlesCount; i++) {
                    const particle = document.createElement('div');
                    particle.classList.add('particle');
                    
                    const size = Math.random() * 4 + 1; // 更小的粒子
                    particle.style.width = `${size}px`;
                    particle.style.height = `${size}px`;
                    
                    // 粒子集中在左侧区域
                    const x = Math.random() * animationSide.offsetWidth * 0.7;
                    const y = Math.random() * animationSide.offsetHeight;
                    particle.style.left = `${x}px`;
                    particle.style.top = `${y}px`;
                    
                    particles.push({
                        element: particle,
                        x, y, size,
                        speedX: (Math.random() - 0.5) * 0.3, // 更慢的速度
                        speedY: (Math.random() - 0.5) * 0.3
                    });
                    
                    animationSide.appendChild(particle);
                }

                // 创建稀疏的连接线
                for (let i = 0; i < linesCount; i++) {
                    const line = document.createElement('div');
                    line.classList.add('data-line');
                    line.style.width = '80px';
                    line.style.height = '1px'; // 更细的线条
                    
                    const startX = Math.random() * animationSide.offsetWidth * 0.7;
                    const startY = Math.random() * animationSide.offsetHeight;
                    line.style.left = `${startX}px`;
                    line.style.top = `${startY}px`;
                    
                    const angle = Math.random() * Math.PI * 2;
                    line.style.transform = `rotate(${angle}rad)`;
                    
                    lines.push({
                        element: line,
                        startX, startY, angle,
                        length: 80 + Math.random() * 100
                    });
                    
                    animationSide.appendChild(line);
                }

                // 鼠标移动交互（粒子会受鼠标排斥）
                animationSide.addEventListener('mousemove', (e) => {
                    const rect = animationSide.getBoundingClientRect();
                    mouse.x = e.clientX - rect.left;
                    mouse.y = e.clientY - rect.top;
                });

                // 动画循环
                function animate() {
                    particles.forEach(particle => {
                        // 粒子自然移动
                        particle.x += particle.speedX;
                        particle.y += particle.speedY;
                        
                        // 边界检测（限制在左侧区域）
                        if (particle.x < 0 || particle.x > animationSide.offsetWidth * 0.8) {
                            particle.speedX *= -1;
                        }
                        if (particle.y < 0 || particle.y > animationSide.offsetHeight) {
                            particle.speedY *= -1;
                        }
                        
                        // 鼠标排斥效果
                        if (mouse.x && mouse.y) {
                            const dx = mouse.x - particle.x;
                            const dy = mouse.y - particle.y;
                            const distance = Math.sqrt(dx * dx + dy * dy);
                            
                            if (distance < mouse.radius) {
                                const force = (mouse.radius - distance) / mouse.radius;
                                const angle = Math.atan2(dy, dx);
                                
                                particle.x -= Math.cos(angle) * force * 0.6;
                                particle.y -= Math.sin(angle) * force * 0.6;
                            }
                        }
                        
                        // 更新粒子位置
                        particle.element.style.left = `${particle.x}px`;
                        particle.element.style.top = `${particle.y}px`;
                    });

                    // 稀疏更新连接线（仅连接近距离粒子）
                    lines.forEach((line, index) => {
                        const p1 = particles[Math.floor(Math.random() * particles.length)];
                        const p2 = particles[Math.floor(Math.random() * particles.length)];
                        
                        if (p1 && p2 && p1 !== p2) {
                            const dx = p2.x - p1.x;
                            const dy = p2.y - p1.y;
                            const distance = Math.sqrt(dx * dx + dy * dy);
                            
                            // 只连接较近距离的粒子
                            if (distance < 150 && distance > 40) {
                                line.startX = p1.x;
                                line.startY = p1.y;
                                line.angle = Math.atan2(dy, dx);
                                line.length = distance;
                                
                                line.element.style.left = `${line.startX}px`;
                                line.element.style.top = `${line.startY}px`;
                                line.element.style.transform = `rotate(${line.angle}rad)`;
                                line.element.style.width = `${line.length}px`;
                                line.element.style.opacity = 1 - (distance / 150);
                            } else {
                                line.element.style.opacity = 0;
                            }
                        }
                    });

                    requestAnimationFrame(animate);
                }

                animate();
            }

            // 破碎转场效果
            function triggerShatterEffect(callback) {
                // 清除之前的碎片
                shatterEffect.innerHTML = '';
                shatterEffect.style.display = 'block';
                
                // 获取认证区域的位置和尺寸
                const rect = authContainer.getBoundingClientRect();
                shatterEffect.style.left = `${rect.left}px`;
                shatterEffect.style.top = `${rect.top}px`;
                shatterEffect.style.width = `${rect.width}px`;
                shatterEffect.style.height = `${rect.height}px`;
                
                // 创建碎片（匹配整体渐变背景）
                const piecesX = 15;
                const piecesY = 10;
                const pieceWidth = rect.width / piecesX;
                const pieceHeight = rect.height / piecesY;
                
                for (let y = 0; y < piecesY; y++) {
                    for (let x = 0; x < piecesX; x++) {
                        const piece = document.createElement('div');
                        piece.classList.add('shatter-piece');
                        
                        piece.style.width = `${pieceWidth}px`;
                        piece.style.height = `${pieceHeight}px`;
                        piece.style.left = `${x * pieceWidth}px`;
                        piece.style.top = `${y * pieceHeight}px`;
                        
                        // 渐变背景的碎片样式
                        piece.style.backgroundImage = `url('data:image/svg+xml;base64,${btoa(`
                            <svg xmlns="http://www.w3.org/2000/svg" width="${rect.width}" height="${rect.height}">
                                <rect width="${rect.width}" height="${rect.height}" fill="url(#gradient)" />
                                <defs>
                                    <linearGradient id="gradient" x1="0%" y1="0%" x2="100%" y2="0%">
                                        <stop offset="0%" style="stop-color:#0f172a;" />
                                        <stop offset="100%" style="stop-color:#1e293b;" />
                                    </linearGradient>
                                </defs>
                            </svg>
                        `)}')`;
                        piece.style.backgroundPosition = `-${x * pieceWidth}px -${y * pieceHeight}px`;
                        
                        shatterEffect.appendChild(piece);
                        
                        // 随机动画方向和距离
                        const angle = (Math.random() * Math.PI * 2);
                        const distance = 100 + Math.random() * 300;
                        const delay = (x + y) * 0.02;
                        
                        // 应用动画
                        setTimeout(() => {
                            piece.style.transform = `translate(${Math.cos(angle) * distance}px, ${Math.sin(angle) * distance}px) rotate(${Math.random() * 360}deg)`;
                            piece.style.opacity = 0;
                        }, delay * 1000);
                    }
                }
                
                // 动画完成后隐藏效果并执行回调
                setTimeout(() => {
                    shatterEffect.style.display = 'none';
                    if (callback) callback();
                }, 1000);
            }

            // 初始视图设置
            updateView();
        });
    </script>
</body>
</html>